package no.netlight.gotogate.client;

import java.util.ArrayList;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class RoutePlanner implements EntryPoint {

	// GUI elements
	private VerticalPanel mainPanel = new VerticalPanel();
	private FlexTable routeFlexTable = new FlexTable();
	private HorizontalPanel addPanel = new HorizontalPanel();
	private TextBox newStopBox = new TextBox();
	private TextBox departureTimeBox = new TextBox();
	private TextBox arivalTimeBox = new TextBox();
	private TextBox byBox = new TextBox();
	private Button addStopButton = new Button("Go!");
	private Button removeRouteSegmentButton = new Button("X");
	private Button availableRoutesButton = new Button("Show Available Routes");

	// Datastructures
	private ArrayList<String[]> route = new ArrayList<String[]>();

	// EventHandlers
	private KeyPressHandler enterHotKeyHandler = new KeyPressHandler() {
		public void onKeyPress(KeyPressEvent event) {
			if (event.getCharCode() == KeyCodes.KEY_ENTER) {
				addStop();
			}
		}
	};
	private ClickHandler addStopClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
			addStop();
		}
	};
	private ClickHandler removeBtnListener = new ClickHandler() {
		public void onClick(ClickEvent event) {
			int removeIndex = route.size();

			// Removes the last row in the dataset, and puts the remove route
			// segment button at the new last row
			if (removeIndex != 0) {
				route.remove(removeIndex - 1);
				routeFlexTable.removeRow(removeIndex);
				if (removeIndex != 1) {
					routeFlexTable.setWidget(removeIndex - 1, 5,
							removeRouteSegmentButton);
				}
			}
		}
	};
	private ClickHandler showAvailableClickHandler = new ClickHandler() {
		public void onClick(ClickEvent event) {
	        showAvailableRoutes();
		}
		
		//JSNI function that opens a HTML file
		private native void showAvailableRoutes() /*-{ 
        	$wnd.location.href = "http://127.0.0.1:8888/Available.html?gwt.codesvr=127.0.0.1:9997"; 
    	}-*/; 
	};

	/**
	 * Entry Point method.
	 */
	public void onModuleLoad() {

		// Add styles to elements in the route table
		routeFlexTable.getRowFormatter().addStyleName(0, "routeTableHeader");
		routeFlexTable.getCellFormatter().addStyleName(0, 1,
				"routeListNumericColumn");
		routeFlexTable.getCellFormatter().addStyleName(0, 3,
				"routeListNumericColumn");
		routeFlexTable.getCellFormatter().addStyleName(0, 5,
				"routeListRemoveButtonColumn");
		routeFlexTable.addStyleName("routeList");

		// Defines table headers for Manual Route Table
		routeFlexTable.setText(0, 0, "From");
		routeFlexTable.setText(0, 1, "AT");
		routeFlexTable.setText(0, 2, "TO");
		routeFlexTable.setText(0, 3, "ARIVAL");
		routeFlexTable.setText(0, 4, "BY");

		// Set default values for the input text boxes
		newStopBox.setText("Name of stop");
		departureTimeBox.setText("HHMM");
		arivalTimeBox.setText("HHMM");
		byBox.setText("Trasportation");

		// Assemble add panel
		addPanel.add(newStopBox);
		addPanel.add(departureTimeBox);
		addPanel.add(arivalTimeBox);
		addPanel.add(byBox);
		addPanel.add(addStopButton);

		// Assemble main panel
		mainPanel.add(routeFlexTable);
		mainPanel.add(addPanel);
		mainPanel.add(availableRoutesButton);

		// Wrapping the widget around the ManualRoutePlanner around the div
		RootPanel.get("RoutePlanner").add(mainPanel);

		// Sets entry focus to the textBox
		newStopBox.setFocus(true);

		// Listen for mouse events from the buttons
		addStopButton.addClickHandler(addStopClickHandler);
		removeRouteSegmentButton.addClickHandler(removeBtnListener);
		availableRoutesButton.addClickHandler(showAvailableClickHandler);
		
		
		// Listen for keyboard events in the input boxes
		newStopBox.addKeyPressHandler(enterHotKeyHandler);
		departureTimeBox.addKeyPressHandler(enterHotKeyHandler);
		arivalTimeBox.addKeyPressHandler(enterHotKeyHandler);
		byBox.addKeyPressHandler(enterHotKeyHandler);
	}

	public void addStop() {
		// Row values
		final String stop = newStopBox.getText().toUpperCase().trim();
		final String depa = departureTimeBox.getText().toUpperCase().trim();
		final String ariv = arivalTimeBox.getText().toUpperCase().trim();
		final String by = byBox.getText().toUpperCase().trim();

		// Define regex
		final String regexAll = "^[0-9A-Z\\s\\.]{1,}$";
		final String regexNum = "^(([0-1][0-9])|([2][0-3]))([0-5][0-9])$";

		// Set default focus
		newStopBox.setFocus(true);

		// Check if input matches regex
		if (!stop.matches(regexAll)) {
			Window.alert("'" + stop + "' is not a valid input!");
			newStopBox.selectAll();
			return;
		} else if (!depa.matches(regexNum)) {
			Window.alert("'" + depa + "' is not a valid input!");
			departureTimeBox.selectAll();
			return;
		} else if (!ariv.matches(regexNum)) {
			Window.alert("'" + ariv + "' is not a valid input!");
			arivalTimeBox.selectAll();
			return;
		} else if (!by.matches(regexAll)) {
			Window.alert("'" + by + "' is not a valid input!");
			byBox.selectAll();
			return;
		}

		// make sure arival time is greater than departure time, and that the
		// next departure time is greater than this arival time
		if (true) {

		}

		// Clear input text boxes
		newStopBox.setText("");
		departureTimeBox.setText("");
		arivalTimeBox.setText("");
		byBox.setText("");

		// If the stop has been used before, don't add to the list
		if (route.contains(stop)) {
			return;
		}

		// If this is the first stop added. Then it will arive at the airport
		int row = routeFlexTable.getRowCount();
		String lastStop = "AIRPORT";
		if (row - 1 != 0) {
			lastStop = routeFlexTable.getText(row - 1, 0);
		}

		// Add stop to list
		route.add(new String[] { stop, depa, ariv, lastStop, by });

		routeFlexTable.setText(row, 0, stop);
		routeFlexTable.setText(row, 1, depa);
		routeFlexTable.setText(row, 3, ariv);
		routeFlexTable.setText(row, 2, lastStop);
		routeFlexTable.setText(row, 4, by);

		// Add css formating to the added row
		routeFlexTable.getCellFormatter().addStyleName(row, 0,
				"routeListTextColumn");
		routeFlexTable.getCellFormatter().addStyleName(row, 1,
				"routeListNumericColumn");
		routeFlexTable.getCellFormatter().addStyleName(row, 2,
				"routeListTextColumn");
		routeFlexTable.getCellFormatter().addStyleName(row, 3,
				"routeListNumericColumn");
		routeFlexTable.getCellFormatter().addStyleName(row, 4,
				"routeListTextColumn");
		routeFlexTable.getCellFormatter().addStyleName(row, 5,
				"routeListButtonColumn");

		// move the remove row button one row down
		routeFlexTable.remove(removeRouteSegmentButton);
		routeFlexTable.setWidget(row, 5, removeRouteSegmentButton);
	}

}